﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

using System.Timers;
using System.Windows;

using MyFIFO;


using VtcPositionDemo.Common.Utils;

namespace VtcPositionDemo.Driver
{

    public enum RunState
    {
   
        INIT,
        LAUNCHING,
        ATS_READYING, //ATS准备中
        ATS_RUNING,   // ATS 运行中
        SUBSCRIBING,  //正在订阅
        CLOSING,
        CLOSED
    }
    public class AtsBt
    {
        #region ats按钮类
        public string Caption { get; set; }
        #endregion
    }

    public class AtsParam
    {
        #region ats参数
        public string Name; // 参数名
        public double Val;  // 参数值
        public int Handle; // 句柄
        #endregion
    }

    public class VtcRobot
    {
        
        public RunState State
        {
            get { return this.m_state; }
            set
            {
                this.m_state = value;
                if (this.OnRobotEvent != null)
                {
                    RobotEventArgs e = new RobotEventArgs(RobotEventType.StateChanged, value);
                    this.OnRobotEvent(this, e);
                }
            }
        }
        //通道
        public List<HandleVin> handleVins = new List<HandleVin>();
        private RunState m_state = RunState.INIT;
        private Timer m_timer = new Timer();
        private vtc.LogCallback m_logCallBack = null;
        public uint AtsHandle { get; private set; }


        /// <summary>
        /// 回调日志
        /// </summary>
        private ConcurrentQueue<VtcMsg> VtcMsgQueue = new ConcurrentQueue<VtcMsg>();

        public List<AtsBt> BtList { get; private set; }  // ats程序对应的所有按钮
        public List<AtsParam> ParamList { get; private set; } // ats程序对应的所有参数


        public enum RobotEventType
        {
            #region 
            ReadData,// 读数据
            StateChanged,   // 状态改变
            VtcMsg,  // vtc驱动发出的消息
            PushBtn,  //按钮执行成功,
             SpeedChange
            #endregion
        }
        public class RobotEventArgs : EventArgs
        {
            #region
            public readonly RobotEventType mType;
            public readonly object mVal;
            public RobotEventArgs(RobotEventType mt, object val)
            {
                this.mType = mt;
                this.mVal = val;
            }
            #endregion
        }
        public delegate void RobotEvented(object sender, RobotEventArgs e);
        public event RobotEvented OnRobotEvent;


        private void OutVtcMsg(VtcMsg msg)
        {
            if (this.OnRobotEvent != null)
            {
                RobotEventArgs e = new RobotEventArgs(RobotEventType.VtcMsg, msg);
                this.OnRobotEvent(this, e);
            }
        }

        private void OutPushBtnMsg(String btnName)
        {
            if (this.OnRobotEvent != null)
            {
                RobotEventArgs e = new RobotEventArgs(RobotEventType.PushBtn, btnName);
                this.OnRobotEvent(this, e);
            }
        }


        private void OutPutReadData(ChannelTransmitMsg chanelMsg2)
        {
            if (this.OnRobotEvent != null)
            {
          
                RobotEventArgs e = new RobotEventArgs(RobotEventType.ReadData, chanelMsg2);
                this.OnRobotEvent(this, e);
            }
        }
        private void OutSpeedChange(double v)
        {
            RobotEventArgs e = new RobotEventArgs(RobotEventType.SpeedChange, v);
            this.OnRobotEvent(this, e);
        }


        public VtcRobot()
        {
            this.AtsHandle = 0;
            this.m_timer.Interval = 100;
            this.m_timer.Elapsed += M_timer_Tick;
            this.m_logCallBack = new vtc.LogCallback(LogCallBack);


            this.BtList = new List<AtsBt>();
            this.ParamList = new List<AtsParam>();

            HandleVin handleVin = new HandleVin();
            handleVin.label = "自反馈位移";
            handleVin.handle = 0;
            handleVins.Add(handleVin);
        }


        public void Launch()
        {
            if (this.m_state == RunState.INIT)
            {
                m_timer.Start();
            }
            else
            {
                AtsStart();
            }

        }


        public static bool isAtsLoad = false;
        public void AtsLoad()
        {
            if(this.m_state == RunState.INIT)
            {
                MessageBox.Show("未atsLaunch");
                return;
            }
            if (this.m_state == RunState.LAUNCHING)
            {
                MessageBox.Show("LAUNCHING 中");
                return;
            }
            this.AtsHandle = vtc.AtsLoad(ConfigUtil.atsJsonFile);
    
            LogUtil.log(this.AtsHandle);
            
        }



        public void AtsStart()
        {
         
            String atsStr = FileUtil.GetJsonFile(ConfigUtil.atsJsonFile);
            uint ver=vtc.VtcGetDllVer();
            double version = Data.Data_Dvb2Float(ver);
            vtc.AtsStart(this.AtsHandle, atsStr);
            return;
        }

        public void setSpeed(double v)
        {
            uint hWdw = vtc.VtcUseController("#1C");
            vtc.VtcSetRefActMove(hWdw, v);
            vtc.VtcCtrlOpen(hWdw);
            OutSpeedChange(v);
        }

        public void VtcSwitchOn(string tag,bool v)
        {
            uint hSwitch = vtc.VtcUseSwitch(tag);
            if (v)
            {
                vtc.VtcSwitchOn(hSwitch,1);
            }
            else
            {
                vtc.VtcSwitchOn(hSwitch,0);
            }
        }

        public List<string> GetAxiList()
        {
            #region 获取当前ats下轴集合
            List<string> axiList = new List<string>();
            if (true)
            {
                var buf = new byte[1000];
                var n = vtc.AtsGetAxisList(this.AtsHandle, buf);
                var strs = System.Text.Encoding.Default.GetString(buf);
                strs = strs.Substring(0, strs.IndexOf('\0'));
                char[] ge = { ',' };
                var sarray = strs.Split(ge);
                foreach (var sa in sarray)
                {
                    if (sa.Length > 0)
                    {
                        axiList.Add(sa);
                    }
                }
            }
            return axiList;
            #endregion
        }


        public void FreshAtsButton()
        {
            #region 读出当前ats下所有按钮    
            if (true)
            {
                this.BtList.Clear();

                var axiList = this.GetAxiList();
                for (int i = 0; i < axiList.Count; i++)
                {
                    var btList = this.GetAxisButtonList(i); // 获取轴下面的按钮
                    foreach (var bt in btList)
                    {
                        AtsBt abt = new AtsBt();
                        abt.Caption = bt;
                        this.BtList.Add(abt);
                    }
                    var actList = this.GetActionList(i);
                    for (int j = 0; j < actList.Count; j++)
                    {
                        btList = this.GetActionButtonList(i, j);
                        foreach (var bt in btList)
                        {
                            AtsBt abt = new AtsBt();
                            abt.Caption = bt;
                            this.BtList.Add(abt);
                        }
                    }
                }

                Console.WriteLine(this.BtList);

            }
            #endregion
        }



        public List<string> GetActionList(int axiIndex)
        {
            #region 获取当前ats下指定轴下动作集合
            List<string> actList = new List<string>();
            if (true)
            {
                var buf = new byte[1000];
                var n = vtc.AtsGetActionList(this.AtsHandle, axiIndex, buf);
                var strs = System.Text.Encoding.Default.GetString(buf);
                strs = strs.Substring(0, strs.IndexOf('\0'));
                char[] ge = { ',' };
                var sarray = strs.Split(ge);
                foreach (var sa in sarray)
                {
                    if (sa.Length > 0)
                    {
                        actList.Add(sa);
                    }
                }
            }
            return actList;
            #endregion
        }

        public List<string> GetAxisButtonList(int axiIndex)
        {
            #region 获取当前ats下指定轴下按钮集合
            List<string> btList = new List<string>();
            if (true)
            {
                var buf = new byte[1000];
                var n = vtc.AtsGetAxisButtonList(this.AtsHandle, axiIndex, buf);
                var strs = System.Text.Encoding.Default.GetString(buf);
                strs = strs.Substring(0, strs.IndexOf('\0'));
                char[] ge = { ',' };
                var sarray = strs.Split(ge);
                foreach (var sa in sarray)
                {
                    if (sa.Length > 0)
                    {
                        btList.Add(sa);
                    }
                }
            }
            return btList;
            #endregion
        }

        public List<string> GetActionButtonList(int axiIndex, int actionIndex)
        {
            #region 获取当前ats下指定轴下指定动作下按钮集合
            List<string> btList = new List<string>();
            if (true)
            {
                var buf = new byte[1000];
                var n = vtc.AtsGetActionButtonList(this.AtsHandle, axiIndex, actionIndex, buf);
                var strs = System.Text.Encoding.Default.GetString(buf);
                strs = strs.Substring(0, strs.IndexOf('\0'));
                char[] ge = { ',' };
                var sarray = strs.Split(ge);
                foreach (var sa in sarray)
                {
                    if (sa.Length > 0)
                    {
                        btList.Add(sa);
                    }
                }
            }
            return btList;
            #endregion
        }






        public void AtsPushButton(string btName)
        {
            vtc.AtsPushButton( this.AtsHandle,  btName);
        }

        public void HandPushButton(string btName)
        {
            if (this.m_state == RunState.INIT)
            {
                MessageBox.Show("未atsLaunch");
                return;
            }

            if ("api上升".Equals(btName))
            {
                setSpeed(1.0);
            }
            else if("api下降".Equals(btName))
            {
                setSpeed(-1.0);
              
            }
            else if ("api暂停".Equals(btName))
            {
                setSpeed(0.0);
            }

        }


        public void RunStart()
        {
            uint ver = vtc.VtcGetDllVer();
            double version = Data.Data_Dvb2Float(ver);
            VtcMsg vtcMsg = new VtcMsg();
            vtcMsg.MsgId = 0;
            vtcMsg.Msg = "vtc.version"+ version + "";
            this.OutVtcMsg(vtcMsg);
            this.Launch();
        }


        public void RunAtsTerminate()
        {
            vtc.AtsTerminate(this.AtsHandle);
        }

        public void RunAtsStart()
        {
            if(this.State == RunState.ATS_READYING || this.State == RunState.CLOSED)
            {
                this.AtsStart();
                this.State = RunState.ATS_RUNING;
            }
        }


        private void LogCallBack(ushort msgId, uint ms, string msg)
        {
            VtcMsg cm = new VtcMsg();
            cm.MsgId = (ushort)msgId;
            cm.Ms = ms;
            cm.Msg = msg;

            //定时器处理
            this.VtcMsgQueue.Enqueue(cm);
        }

        public static bool isSubScribIng = false;


        private void M_timer_Tick(object sender, EventArgs e)
        {
            //读vtc回调日志
            VtcMsg cm = null;
            while (this.VtcMsgQueue.TryDequeue(out cm))
            {
                this.OutVtcMsg(cm);
                if (cm.MsgId >= vtc.LAUNCH_OK && this.m_state == RunState.LAUNCHING)
                {
                    this.State = RunState.SUBSCRIBING;
                }
                if (cm.MsgId == vtc.ATS_LOAD_OK)
                {
                    this.State = RunState.ATS_READYING;
                }
                if (cm.MsgId == vtc.ATS_STARTED )
                {
                    this.State = RunState.ATS_RUNING;
                }
                if (cm.MsgId == vtc.ATS_PUSH_BTN)
                {
                    this.OutPushBtnMsg(cm.Msg);
                }
                if(cm.MsgId == vtc.ATS_OVER1)
                {
                    this.State = RunState.CLOSED;
                }
            }

         

            switch (this.m_state){
                case RunState.INIT:
                    {
                        this.State = RunState.LAUNCHING;
                        String vtcFileStr = FileUtil.GetJsonFile(ConfigUtil.vtcJsonFile);
                        vtc.VtcCreate(vtcFileStr, this.m_logCallBack);
                        break;
                    }
                case RunState.SUBSCRIBING:
                    {
                        if (isSubScribIng == false)
                        {
                            for (int i = 0; i < handleVins.Count; i++)
                            {
                                HandleVin handleVin = handleVins[i];
                                handleVin.handle = vtc.VtcSubscribeForVin(handleVin.label);
                            }
                            isSubScribIng = true;
                            this.AtsLoad();
                        }
                        break;
                    }
            }



            if (this.State == RunState.ATS_RUNING || this.State==RunState.ATS_READYING)
            {
                var handleVin = this.handleVins[0];
                var n = vtc.VtcTakeSnapshot();
                for (int i = 0; i < n; i++)
                {
                    uint ms = vtc.VtcGetTime(i);
                    var dvb = vtc.VtcGetVin(handleVin.handle, i);

                   // Console.WriteLine($"ms==>{ms} {Data.Data_Dvb2Float(dvb)}");
                    ChannelTransmitMsg cm2 = new ChannelTransmitMsg(ms, 2, 3, dvb);
                    this.OutPutReadData(cm2);
                }
            }

        }
    }



}